# -*- coding: utf-8 -*-
# @desc: 
# @file: main.py
# @author: Lin Jackey Lyu (me@linlyu.com)
# @date: 2019/2/27 9:23
from core.config import YamlConfig
from importlib import import_module
import pickle
from rqalpha import run_code, run_file
import sys
import time

from selection.base_selector import AbstractSelector
from template.code_generator import BTCodeGenerator, PolicyClass


def parse_parameters(argv) -> (YamlConfig, AbstractSelector):
    assert len(argv) == 4

    config = YamlConfig(argv[0])
    policy = PolicyClass(int(argv[1]))
    module = import_module(argv[2])
    klass = getattr(module, argv[3])
    selector = klass()
    if not isinstance(selector, AbstractSelector):
        raise ValueError("Given selector is not an ")
    return config, selector, policy


def main(argv=None):
    if argv is None:
        argv = sys.argv[1:]
    if len(argv) != 4:
        print("""
        Backtesting utility based on RQalpha and its bundle data.
        Usage: 
            python {name} <config file in Yaml> <policy_type> <selector module> <select class name>
        
        policy types:
            1 - 按照yaml配置文件中的调仓周期进行调仓，如果有设置止盈止损条件，则每天检查是否止盈或止损进行主动调仓。
            2 - 按照selector中给出的order进行买卖，不允许设置止盈止损条件，完全按照order进行买卖
            3 - 输入是每日持仓股票的场景。新的一日，持仓股票不同于前一日时，会卖掉不在的股票，并调整新一日股票市值到等权重。
            4 - 输入是（date, stock）模式，指定在date日买入stock，按照配置参数中的 rebalance_interval 进行周期卖出调仓。
        example:
            
            python {name} etc/config-dev.yml 1 selection.example_selector DummySelector
        """.format(name=sys.argv[0]))
        return 1
    config, selector, policy_type = parse_parameters(argv)
    print("policy type is ", policy_type)
    print("Config file is ", config)
    print("Selector is ", selector)
    duration, code, bt_cfg = BTCodeGenerator.generate(config=config, selector=selector, policy_type=policy_type)

    if config.core.debug:
        filename = "strategy-duration-{}.py".format(duration)
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(code)
        print("strategy file generated in {} for debugging.".format(filename))
        bt_result = run_file(strategy_file_path=filename, config=bt_cfg)
    else:
        bt_result = run_code(code=code, config=bt_cfg)

    if  bt_result is None:
        print("回测失败。")
        return 1

    print("Backtesting is finished. Collecting results ...")
    target_file = 'bt-result-duration-{}.pk'.format(policy_type)
    with open(target_file, 'wb') as f:
        pickle.dump(bt_result['sys_analyser'], f)
    print("Backtesting result saved in ", target_file)
    print("""You can use these two comands to see,
        收益率曲线:\t rqalpha plot {pk_file} [--plot-save {pk_file}.png]
        交易明细:\t 
                    mkdir results
                    rqalpha report {pk_file} results
    """.format(pk_file=target_file))
    return 0


if __name__ == "__main__":
    print("Starting ...")
    start = time.time()
    main()
    cost = time.time() - start
    print("End. cost {:.2f} seconds".format(cost))
